﻿using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using TTGame;

/*
 * DamageInfo
 * 用于传递伤害参数。
 *
 * 有些伤害的参数不能立即计算，需要保存，等到合适的时机再计算。
 *
 * 依赖：
 *
 * ！不写重复代码！
 * @author TTun
 * @date 7/24/2017 11:53:03 AM
 */
namespace TTGameEngine {
public enum DamageType {
    Damage,
    Healing,
}

//伤害来源
public enum DamageSource {
    Skill,
    Buff,
}

public enum ControlState {
    None,
    Stun,   //击晕
    Sheep,  //变羊
}

public enum HurtType {
    NoHurtAnim, //没有受伤动画
    LightHurt, //轻微受伤
    HeavyHurt, //重受伤
    KnockDown,//击倒
}

public class DamageInfo {
    public DamageType damageType = DamageType.Damage;
    public int damage;      //是正数。加血、伤害由damageType区分。
    public string attackerGID; //攻击对象索引。对象的全局唯一ID。
    public string receiverGID; //被攻击者。
    public PuppetCampID attackerCampID = PuppetCampID.None;
    public DamageSource dmgSource = DamageSource.Skill;
    //更多可选数据。根据需要，有就尽量填写。
    public Vector3 hitPoint;    //击中点坐标
    public Vector3 hitPointOffset;   //击中点相对于被击中者坐标。
    public HurtType hurtType = HurtType.NoHurtAnim;
    public bool isHurtForward = true; //true=正面受伤  false=背面受伤
    public uint skillCastID = 0;          //如果因技能受伤，填写技能施法ID
    public int skillID = 0;         //如果因技能受伤，填写技能ID
    public int buffID = 0;          //如果因Buff受伤，填写BuffID
    public float buffLastTime = 0f;  //如果因Buff受伤，填写Buff剩余时间
    public List<int> buffIDs = new List<int>(); //触发的新Buff
    public bool isCanAddAnger = true;  //被打者是否可以增加怒气。
    private bool m_isNoHarm = false;    //是否没有伤害，仅触发特效和Buff。
    //--------还没用上-------
    public string controlAnim;              //控制状态动画
    public ControlState controlAciont = ControlState.None;   //控制状态
    //--------伤害计算参数--------
    int attackerATK = 0;         //攻击者攻击力
    int reciverDEF = 0;          //受伤者防御力
    float skillDmgFactor = 1f;   //技能伤害调整百分比
    float skillDmgAdd = 0;         //技能伤害调整数值
    float critRate = 0f;         //暴击率
    float FetterAtkRate = 1f;    //羁绊攻击力增加

    public bool IsNoHarm {
        set {
            m_isNoHarm = value;
            if(m_isNoHarm)
                damage = 0;
        }
        get { return m_isNoHarm; }
    }

    private DamageInfo() { }

    static public DamageInfo CreateDamageInfo(
        Puppet attacker,
        Puppet reciver,
        int aSkillID, uint aCastID,
        float aSkillDmgFactor,
        float aSkillDmgAdd,
        float aCritRate,
        float aFetterAtkRate,
        DamageSource aDmgSource,
        DamageType aDmgType = DamageType.Damage
    ) {
        DamageInfo info = new DamageInfo();
        info.Init();
        info.attackerGID = attacker.GetGID();
        info.receiverGID = reciver.GetGID();
        info.attackerCampID = attacker.CampID;
        info.skillCastID = aCastID;
        info.skillID = aSkillID;
        info.attackerATK = attacker.AttackPoint;
        info.reciverDEF = reciver.DefensePoint;
        info.skillDmgAdd = aSkillDmgAdd;
        info.skillDmgFactor = aSkillDmgFactor;
        info.critRate = aCritRate;
        info.FetterAtkRate = aFetterAtkRate;
        info.dmgSource = aDmgSource;
        info.damageType = aDmgType;
        info.damage = info.CalcDamage();
        return info;
    }

    static public DamageInfo CreateDamageInfoWithRealDamage(
        string attackerGID,
        string reciverGID,
        int aDmg,
        int aSkillID, uint aCastID,
        int aBuffID, float aLastTime,
        DamageSource aDmgSource,
        DamageType aDmgType = DamageType.Damage
    ) {
        DamageInfo info = new DamageInfo();
        info.Init();
        info.attackerGID = attackerGID;
        info.receiverGID = reciverGID;
        info.damage = aDmg;
        info.skillCastID = aCastID;
        info.skillID = aSkillID;
        info.buffID = aBuffID;
        info.buffLastTime = aLastTime;
        info.dmgSource = aDmgSource;
        info.damageType = aDmgType;
        return info;
    }

    //重置参数。
    public void Init() {
        buffLastTime = 0;
        damageType = DamageType.Damage;
        damage = 0;      //是正数。加血、伤害由damageType区分。
        attackerGID = ""; //攻击对象索引。对象的全局唯一ID。
        receiverGID = ""; //被攻击者。
        attackerCampID = PuppetCampID.None;
        dmgSource = DamageSource.Skill;
        //更多可选数据。根据需要，有就尽量填写。
        hitPoint = Vector3.zero;    //击中点坐标
        hitPointOffset = Vector3.zero;   //击中点相对于被击中者坐标。
        hurtType = HurtType.NoHurtAnim;
        isHurtForward = true; //true=正面受伤  false=背面受伤
        skillCastID = 0;          //如果因技能受伤，填写技能施法ID
        skillID = 0;         //如果因技能受伤，填写技能ID
        buffID = 0;          //如果因Buff受伤，填写BuffID
        buffLastTime = 0f;  //如果因Buff受伤，填写Buff剩余时间
        buffIDs.Clear(); ; //触发的新Buff
        isCanAddAnger = true;  //被打者是否可以增加怒气。
        m_isNoHarm = false;    //是否没有伤害，仅触发特效和Buff。
        //--------还没用上-------
        controlAnim = "";              //控制状态动画
        controlAciont = ControlState.None;   //控制状态
        //--------伤害计算参数--------
        attackerATK = 0;         //攻击者攻击力
        reciverDEF = 0;          //受伤者防御力
        skillDmgFactor = 1f;   //技能伤害调整百分比
        skillDmgAdd = 0;         //技能伤害调整数值
        critRate = 0f;         //暴击率
        FetterAtkRate = 1f;    //羁绊攻击力增加
    }

    public void SetSkillSourceInfo(int aSkillID, uint aCastID) {
        dmgSource = DamageSource.Skill;
        skillCastID = aCastID;
        skillID = aSkillID;
    }

    public void SetBuffSourceInfo(int aBuffID, float aLastTime) {
        dmgSource = DamageSource.Buff;
        buffID = aBuffID;
        buffLastTime = aLastTime;
    }

    /// <summary>
    /// 计算伤害  返回伤害值>=0
    /// 使用的参数：
    /// ATK
    /// DEF
    /// skillDmgFactor
    /// skillDmgAdd
    /// critRate
    ///
    /// </summary>
    /// <returns></returns>
    int CalcDamage() {
        if(m_isNoHarm) {
            return 0;
        }
        //计算伤害。
        bool isCrit = Tools.IsHitRate(critRate);
        float Dmg = ((attackerATK - reciverDEF) * skillDmgFactor + skillDmgAdd) * FetterAtkRate;
        if(isCrit) {
            Dmg *= 2;
        }
        //最小伤害值为1
        if((attackerATK > 0 || skillDmgAdd > 0) && Dmg < 1)
            return 1;
        if(Dmg <= 0)
            return 0;
        return (int)Dmg;
    }
}

}
